/*
 * Copyright (c) 2007-2008, Thomas Krause (tho.krause@gmail.com)
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *     * Neither the name of gidoo nor the names of its contributors may be used to
 *       endorse or promote products derived from this software without specific
 *       prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.gidoo.cms.editor.resources;

import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
import org.apache.wicket.extensions.ajax.markup.html.form.upload.UploadProgressBar;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.upload.FileUpload;
import org.apache.wicket.markup.html.form.upload.FileUploadField;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.gidoo.cms.GidooCMS;
import org.gidoo.cms.editor.EditorPage;
import org.gidoo.cms.login.GidooCMSSession;
import org.gidoo.cms.helper.ResourceDownloadLink;
import org.gidoo.cms.helper.Tools;

/**
 * 
 * @author thomas
 */
public class ResourcesPanel extends Panel
{ 
  String pagePath;
  EditorPage theParent;
  
  Form formMain;
  FileUploadField fileUpload;
  AutoCompleteTextField txtMIME;
  Button btAdd;
  
  ListView lsvFiles;
  
  public final String[] knownMIMETypes = new String[]
  {
    "application/gtar",
    "application/gzip",
    "application/pdf",
    "application/postscript",
    "application/zip",
    "image/gif",
    "image/jpeg",
    "image/png",
    "text/plain",
    "text/xml",
    "video/mpeg"
  };
  
  
  public ResourcesPanel(String id, Node page, EditorPage parent)
  {
    super(id);
    try
    {
      this.theParent = parent;
      if(page == null)
      {
        this.setVisible(false);
        pagePath = null;
      }
      else
      {
        this.pagePath = page.getPath().substring(1);
      }
      
      
      formMain = new Form("formMain")
      {

        @Override
        protected void onSubmit()
        {
          uploadFile();
        }
      };
      fileUpload = new FileUploadField("fileUpload");
      fileUpload.setRequired(true);

      txtMIME = new AutoCompleteTextField("txtMIME")
      {

        @Override
        protected Iterator getChoices(String input)
        {
          LinkedList<String> result = new LinkedList<String>();
          for(String s : knownMIMETypes)
          {
            if(s.contains(input))
            {
              result.add(s);
            }
          }
          return result.iterator();
        }
      };
      txtMIME.setModel(new Model(""));

      btAdd = new Button("btAdd");
      btAdd.setModel(new Model(getString("add")));

      formMain.add(fileUpload);
      formMain.add(txtMIME);
      formMain.add(btAdd);

      formMain.setMultiPart(true);

      lsvFiles = new ListView("lsvFiles")
      {

        @Override
        protected void populateItem(ListItem item)
        {
          createListItem(item);
        }
      };

      formMain.add(lsvFiles);
      formMain.add(new UploadProgressBar("uploadProgress", formMain));

      add(formMain);

      if(page == null)
      {
        formMain.setVisible(false);
      }
      else
      {
        LinkedList<String> resList = getResourcesList(page);
        lsvFiles.setList(resList);
      }
    }
    catch(RepositoryException ex)
    {
      Logger.getLogger(ResourcesPanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }
    
  }

  private void createListItem(ListItem item)
  {   
    try
    {
      final String resName = item.getModelObjectAsString();
      
      if(pagePath != null)
      {
        Node page = ((GidooCMSSession) getSession()).getJcrRootNode().getNode(pagePath);

        Node drafts = ((GidooCMSSession) getSession()).getJcrRootNode().getNode("drafts");

        Node res = null;
        boolean isPublished = false;
        if(page.hasNode(resName))
        {
          isPublished = true;
          res = page.getNode(resName);
        }
        else if(drafts.hasNode(Tools.path2DraftName(resName)))
        {
          isPublished = false;
          res = drafts.getNode(Tools.path2DraftName(resName));
        }

        if(res == null)
        {
          error(getString("nullproblem"));
          return;
        }

        ResourceDownloadLink lnkFileDownload = new ResourceDownloadLink("lnkFileDownload", res);
        item.add(lnkFileDownload);

        String ps = isPublished ? getString("published") : getString("notpublished");
        String name = res.getName();
        if(!isPublished)
        {
          name = Tools.draftName2Path(name);
          name = name.substring(name.lastIndexOf("/") + 1);
        }

        Label lblFileCaption = new Label("lblFileCaption", new Model(name + " (" + res.getProperty("jcr:mimeType").getString() + ", " + ps + ")"));

        lnkFileDownload.add(lblFileCaption);

        final Node fRes = res;

        Link lnkDelete = new Link("lnkDelete", new Model("delete"))
        {

          @Override
          public void onClick()
          {
            deleteResource(fRes);
          }
        };

        item.add(lnkDelete);
      }
    }
    catch(RepositoryException ex)
    {
      Logger.getLogger(ResourcesPanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }
        
  }
  
  private void deleteResource(Node res)
  {
    try
    {
      String oldPath = Tools.draftName2Path(res.getName());
      Node parent = res.getParent();
      res.remove();      
      parent.save();      
      
      Logger.getLogger(GidooCMS.ACTION_LOGGER).log(Level.INFO,
        "user \"" + ((GidooCMSSession) getSession()).getUsername() + "\" deleted " +
        "resource " + oldPath);
      
      Node root = ((GidooCMSSession) getSession()).getJcrRootNode();
      Node page = root.getNode(pagePath);
      
      lsvFiles.setList(getResourcesList(page));
    }
    catch (RepositoryException ex)
    {
      Logger.getLogger(ResourcesPanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }
  }
  
  private void uploadFile()
  {
    {
      try
      {
        FileUpload u = fileUpload.getFileUpload();
        String mime = txtMIME.getModelObjectAsString();
        if (mime == null || "".equals(mime))
        {
          mime = u.getContentType();
        }
        GidooCMSSession session = (GidooCMSSession) getSession();
        Node drafts = session.getJcrRootNode().getNode("drafts");
        
        Node res = drafts.addNode(
          Tools.path2DraftName(pagePath + "/" + u.getClientFileName()),
          "cms:resource");
        
        res.setProperty("jcr:mimeType", mime);
        res.setProperty("cms:editor", session.getUsername());
        res.setProperty("cms:size", u.getSize());
        res.setProperty("jcr:data", u.getInputStream());
        
        Node root = ((GidooCMSSession) getSession()).getJcrRootNode();
        Node page = root.getNode(pagePath);

        lsvFiles.setList(getResourcesList(page));
        
        info(getString("wasadded"));
        
        
      }      
      catch(RepositoryException ex)
      {
        Logger.getLogger(ResourcesPanel.class.getName()).log(Level.SEVERE, null, ex);
        error(getString("jcrerror"));
      }
      catch(IOException ex)
      {
        Logger.getLogger(ResourcesPanel.class.getName()).log(Level.SEVERE, null, ex);
        error(getString("ioerror"));
      }
    }
  }
  
  
  private LinkedList<String> getResourcesList(Node page) throws RepositoryException
  {
    LinkedList<String> resList = new LinkedList<String>();
    
    if(page == null)
    {
      return resList;
    }
    
    NodeIterator itPage = page.getNodes();
    while(itPage.hasNext())
    {
      Node n = itPage.nextNode();
      if("cms:resource".equals(n.getPrimaryNodeType().getName()))
      {
        resList.add(n.getName());
      }
    }

    NodeIterator itDrafts = 
      ((GidooCMSSession) getSession()).getJcrRootNode().getNode("drafts").getNodes();

    String pathParent = Tools.cleanupFolderPath(page.getPath());
    
    while(itDrafts.hasNext())
    {
      Node n = itDrafts.nextNode();
      if("cms:resource".equals(n.getPrimaryNodeType().getName()))
      {
        String tmpPath = Tools.draftName2Path(n.getName());
        
        tmpPath = Tools.cleanupFolderPath(tmpPath);
        String pathToCompare = tmpPath.substring(0, tmpPath.lastIndexOf("/"));
        
        if(pathToCompare.equals(pathParent))
        {        
          resList.add(tmpPath);
        }
      }
    }
    
    return resList;
  }
  
  public void updateDataAndView(Node page, EditorPage parent)
  {
    try
    {
      this.theParent = parent;
      if(page == null)
      {
        pagePath = null;
      }
      else
      {
        this.pagePath = page.getPath().substring(1);
      }
      lsvFiles.setList(getResourcesList(page));
    }
    catch(RepositoryException ex)
    {
      Logger.getLogger(ResourcesPanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }
    
  }
  
}
